package com.kawins.supers.log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kawins.util.VerifyCodeUtil;
import com.kawins.util.web.RequestUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author rankai
 *         createTime 2018-03-2018/3/5 13:59
 */
@Aspect
public final class SystemLogAspect {

    private static final Logger log = LoggerFactory.getLogger(SystemLogAspect.class);

    /**
     * 是否打印日志 0:不打印 1:全部打印 2:只打印controller 3:只打印service
     */
    private int print = 0;

    /**
     * controller层日志信息
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    public Object systemLog(ProceedingJoinPoint joinPoint) throws Throwable {
        if (print != 0) {
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            Method method = methodSignature.getMethod();
            Class<?> aClass = method.getDeclaringClass();
            if ((print == 1 || print == 2) && (aClass.getAnnotation(Controller.class) != null ||
                    aClass.getAnnotation(RestController.class) != null)) {
                return controllerLogBuild(joinPoint, method);
            } else if ((print == 1 || print == 3) && aClass.getAnnotation(Service.class) != null) {
                return serviceLogBuild(joinPoint, method);
            } else {
                return joinPoint.proceed();
            }
        } else {
            return joinPoint.proceed();
        }
    }

    private Object controllerLogBuild(ProceedingJoinPoint joinPoint, Method method) throws Throwable {
        HttpServletRequest request = RequestUtil.getRequest();
        Map<String, String[]> parameterMap = request.getParameterMap();
        Object proceed;
        long startTime = System.currentTimeMillis();
        proceed = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        String textCode = VerifyCodeUtil.generateTextCode(0, 6, null);
        String className = joinPoint.getThis().getClass().getName(); //通过代理获取当前类名
        String methodName = joinPoint.getSignature().getName(); //获取当前方法名
        log.info("API请求->标识:{},请求的地址:>>{}", textCode, request.getRequestURI());
        log.info("API请求->标识:{},请求人IP:>>{}", textCode, request.getRemoteAddr());
        log.info("API请求->标识:{},请求人TokenId:>>{}", textCode, request.getSession().getId());
        log.info("API请求->标识:{},调用的类:>>{},调用的的方法:>>{}", textCode, className.split("$$")[0], methodName);
        log.info("API请求->标识:{},传入参数(Json):>>{}", textCode, parameterMap == null ? "null" : JSON.toJSONString(parameterMap));
        if (proceed != null) {
            log.info("API请求->标识:{},返回值为:>>{}", textCode, JSONObject.toJSONString(proceed));
        }
        log.info("API请求->标识:{},耗时(AOP):>>{}(毫秒)", textCode, (endTime - startTime));
        return proceed;
    }

    private Object serviceLogBuild(ProceedingJoinPoint joinPoint, Method method) throws Throwable {
        Parameter[] parameters = method.getParameters();
        Object[] args = joinPoint.getArgs();
        Map<String, Object> map = new HashMap<>(parameters.length);
        if (parameters != null && args.length == parameters.length) {
            for (int i = 0; i < parameters.length; i++) {
                map.put(parameters[i].getName(), args[i].toString());
            }
        }
        Object proceed;
        long startTime = System.currentTimeMillis();
        proceed = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        String textCode = VerifyCodeUtil.generateTextCode(0, 6, null);
        String className = joinPoint.getThis().getClass().getName(); //通过代理获取当前类名
        String methodName = joinPoint.getSignature().getName(); //获取当前方法名
        log.info("Server请求->标识:{},调用的类:>>{},调用的的方法:>>{}", textCode, className.split("$$")[0], methodName);
        log.info("Server请求->标识:{},传入参数(Json):>>{}", textCode, JSON.toJSONString(map));
        if (proceed != null) {
            log.info("Server请求->标识:{},返回值为:>>{}", textCode, JSONObject.toJSONString(proceed));
        }
        log.info("Server请求->标识:{},耗时(AOP):>>{}(毫秒)", textCode, (endTime - startTime));
        return proceed;
    }

    public void setPrint(int print) {
        this.print = print;
    }
}
